package com.ease.util {
   import flash.display.Graphics;
   import flash.geom.Point;

   import mx.graphics.IStroke;

   public class GraphicsUtils {
      public static function _drawDashedLine(target:Graphics, stroke:IStroke, pattern:Array, drawingState:DashStruct, x0:Number, y0:Number, x1:Number, y1:Number):void {
         var dX:Number = x1 - x0;
         var dY:Number = y1 - y0;
         var len:Number = Math.sqrt(dX * dX + dY * dY);
         dX /= len;
         dY /= len;
         var tMax:Number = len;


         var t:Number = -drawingState.offset;
         var bDrawing:Boolean = drawingState.drawing;
         var patternIndex:int = drawingState.patternIndex;
         var styleInited:Boolean = drawingState.styleInited;
         while (t < tMax) {
            t += pattern[patternIndex];
            if (t < 0) {
               var x:int = 5;
            }
            if (t >= tMax) {
               drawingState.offset = pattern[patternIndex] - (t - tMax);
               drawingState.patternIndex = patternIndex;
               drawingState.drawing = bDrawing;
               drawingState.styleInited = true;
               t = tMax;
            }

            if (styleInited == false) {
               if (bDrawing)
                  stroke.apply(target, null, null);
               else
                  target.lineStyle(0, 0, 0);
            }
            else {
               styleInited = false;
            }

            target.lineTo(x0 + t * dX, y0 + t * dY);

            bDrawing = !bDrawing;
            patternIndex = (patternIndex + 1) % pattern.length;
         }
      }

      public static function drawDashedLine(target:Graphics, style:DashLineStyle, x1:Number, y1:Number, x2:Number, y2:Number):void {
         var m:Number = 2;
         if ((x1 != x2) || (y1 != y2)) {
            var dashlen:Number = style.dashlen;
            var gaplen:Number = style.gaplen;
            var incrlen:Number = dashlen + gaplen;

            var len:Number = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
            var angle:Number = Math.atan((y2 - y1) / (x2 - x1));
            var steps:uint = len / incrlen;

            var dashstepx:Number = Math.abs(dashlen * Math.cos(angle));
            var dashstepy:Number = Math.abs(dashlen * Math.sin(angle));
            var gapstepx:Number = Math.abs(gaplen * Math.cos(angle));
            var gapstepy:Number = Math.abs(gaplen * Math.sin(angle));

            var stepcount:uint = 0;

            target.lineStyle(style.width, style.color, 1);
            while ((stepcount++) < steps) {
               var dashstartx:Number;
               var dashstarty:Number;
               var dashendx:Number;
               var dashendy:Number;

               if (x2 > x1 && y2 >= y1) { //↘
                  dashstartx = x1 + (stepcount - 1) * (dashstepx + gapstepx) + m;
                  dashstarty = y1 + (stepcount - 1) * (dashstepy + gapstepy) + m;

                  dashendx = dashstartx + dashstepx;
                  dashendy = dashstarty + dashstepy;
               }
               else if (x2 <= x1 && y2 > y1) { //↙
                  dashstartx = x1 - (stepcount - 1) * (dashstepx + gapstepx) - m;
                  dashstarty = y1 + (stepcount - 1) * (dashstepy + gapstepy) + m;

                  dashendx = dashstartx - dashstepx;
                  dashendy = dashstarty + dashstepy;
               }
               else if (x2 < x1 && y2 <= y1) { //↖
                  dashstartx = x1 - (stepcount - 1) * (dashstepx + gapstepx) - m;
                  dashstarty = y1 - (stepcount - 1) * (dashstepy + gapstepy) - m;

                  dashendx = dashstartx - dashstepx;
                  dashendy = dashstarty - dashstepy;
               }
               else if (x2 >= x1 && y2 < y1) { //↗
                  dashstartx = x1 + (stepcount - 1) * (dashstepx + gapstepx) + m;
                  dashstarty = y1 - (stepcount - 1) * (dashstepy + gapstepy) - m;

                  dashendx = dashstartx + dashstepx;
                  dashendy = dashstarty - dashstepy;
               }
               target.moveTo(dashstartx, dashstarty);
               target.lineTo(dashendx, dashendy);
            }

         }
      }


      public static function drawDashedPolyLine(target:Graphics, stroke:IStroke, pattern:Array, points:Array):void {
         if (points.length == 0)
            return;

         var prev:Object = points[0];

         var struct:DashStruct = new DashStruct();
         target.moveTo(prev.x, prev.y);
         for (var i:int = 1; i < points.length; i++) {
            var current:Object = points[i];
            _drawDashedLine(target, stroke, pattern, struct, prev.x, prev.y, current.x, current.y);
            prev = current;
         }
      }

      public static function drawCircleARC(target:Graphics, center:Point, start:Number, angle:Number, radius:Number, stroke:IStroke = null):void {

         var x:Number = center.x;
         var y:Number = center.y;

         var n:Number = Math.ceil(Math.abs(angle) / 45);

         var angleA:Number = angle / n;

         angleA = angleA * Math.PI / 180;

         start = start * Math.PI / 180;

         if (stroke)
            stroke.apply(target, null, null);
         else
            target.lineStyle(0.5, 0x000000);

         target.moveTo(x + radius * Math.cos(start), y + radius * Math.sin(start));
         for (var i:int = 1; i <= n; i++) {
            start += angleA;
            var angleMid:Number = start - angleA / 2;
            var bx:Number = x + radius / Math.cos(angleA / 2) * Math.cos(angleMid);
            var by:Number = y + radius / Math.cos(angleA / 2) * Math.sin(angleMid);
            var cx:Number = x + radius * Math.cos(start);
            var cy:Number = y + radius * Math.sin(start);
            target.curveTo(bx, by, cx, cy);
         }
      }
   }
}

class DashStruct {
   public function init():void {
      drawing = true;
      patternIndex = 0;
      offset = 0;
   }
   public var drawing:Boolean = true;
   public var patternIndex:int = 0;
   public var offset:Number = 0;
   public var styleInited:Boolean = false;
}
